#ifndef CMAINFRAME_HPP
#define CMAINFRAME_HPP

#include <map>
#include <time.h>
#include <shlobj.h>
#include <shtypes.h>
#include <windows.h>
#include <windowsx.h>
#include <strsafe.h>
#include <commctrl.h>

#define IDB_BUTTON_START 1
#define IDB_BUTTON_STOP 2
#define IDB_BUTTON_TDSET 3
#define IDB_BUTTON_XTSET 4
#define IDB_BUTTON_HELP 5

class CMainFrame
{
public:
    CMainFrame()
    {
        m_hWnd = NULL;
        m_hMenu = NULL;
        m_rcMenuBar = {0};
        m_hToolBar = NULL;
        m_rcToolBar = {0};
        m_wcex = {0};
        m_hInstance = NULL;
    }
    ~CMainFrame() {}
    CMainFrame(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        Register(lpszClassName, hInstance);
    }
    CMainFrame(const CMainFrame &) = delete;
    CMainFrame &operator=(const CMainFrame &) = delete;
    HWND GetHWND() const
    {
        return m_hWnd;
    }
    RECT GetToolBarRect()
    {
        return m_rcToolBar;
    }
    RECT GetMenuBarRect()
    {
        return m_rcMenuBar;
    }
    LRESULT Register(LPCTSTR lpszClassName, HINSTANCE hInstance)
    {
        m_wcex = {0};
        m_wcex.cbSize = sizeof(WNDCLASSEX);
        m_wcex.cbClsExtra = 0;                                     // 类的额外内存
        m_wcex.cbWndExtra = 0;                                     // 窗口额外内存
        m_wcex.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); // 背景
        m_wcex.hCursor = LoadCursor(NULL, IDC_ARROW);              // 光标 第一个为NULL代表使用系统提供的光标
        m_wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);            // 图标 第一个为NULL代表使用系统提供的图标
        m_wcex.hInstance = hInstance;                              // 应用程序实例句柄
        m_wcex.lpfnWndProc = CMainFrame::WndProc;                  // 回调函数
        m_wcex.lpszClassName = lpszClassName;                      // 窗口类名称
        m_wcex.lpszMenuName = NULL;                                // 菜单名称
        m_wcex.style = CS_HREDRAW | CS_VREDRAW;                    // 显示风格
        m_hInstance = hInstance;
        if (!RegisterClassEx(&m_wcex))
        {
            MessageBox(NULL, TEXT("Failed to register main window class"), TEXT("Error"), MB_OK | MB_ICONERROR);
            return -1;
        }
        return 0;
    }
    LRESULT Create(UINT uWidth, UINT uHeight, LPCTSTR szWindowName)
    {
        RECT wr;
        wr.left = CW_USEDEFAULT;
        wr.right = uWidth + wr.left;
        wr.top = CW_USEDEFAULT;
        wr.bottom = uHeight + wr.top;
        AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
        // Create the main window
        m_hWnd = CreateWindow(m_wcex.lpszClassName, szWindowName, WS_OVERLAPPEDWINDOW,
                              CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, m_hInstance, this);
        CreateMenuBar(m_hWnd);
        CreateToolBar(m_hWnd);
        SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
        return 0;
    }
    LRESULT CreateMenuBar(HWND hWnd)
    {
        m_hMenu = CreateMenu();
        if (!m_hMenu)
            return -1;
        HMENU pop1 = CreatePopupMenu();
        HMENU pop2 = CreatePopupMenu();
        HMENU pop3 = CreatePopupMenu();
        HMENU pop4 = CreatePopupMenu();
        HMENU pop5 = CreatePopupMenu();
        AppendMenu(m_hMenu, MF_POPUP, (UINT_PTR)pop1, TEXT("File"));
        AppendMenu(m_hMenu, MF_POPUP, (UINT_PTR)pop2, TEXT("Find"));
        AppendMenu(m_hMenu, MF_POPUP, (UINT_PTR)pop3, TEXT("Run"));
        AppendMenu(m_hMenu, MF_POPUP, (UINT_PTR)pop4, TEXT("Tools"));
        AppendMenu(m_hMenu, MF_POPUP, (UINT_PTR)pop5, TEXT("Help"));

        const int IDM_OPEN = 301;
        const int IDM_CLOSE = 302;
        const int IDM_EXIT = 303;
        const int IDM_FIND = 304;
        const int IDM_RUN = 305;
        const int IDM_STOP = 306;
        const int IDM_OPTIONS = 307;
        const int IDM_ABOUT = 308;

        AppendMenu(pop1, MF_STRING, IDM_OPEN, TEXT("Open"));
        AppendMenu(pop1, MF_STRING, IDM_CLOSE, TEXT("Close"));
        AppendMenu(pop1, MF_STRING, IDM_EXIT, TEXT("Exit"));
        AppendMenu(pop2, MF_STRING, IDM_FIND, TEXT("Find"));
        AppendMenu(pop3, MF_STRING, IDM_RUN, TEXT("Run"));
        AppendMenu(pop3, MF_STRING, IDM_STOP, TEXT("Stop"));
        AppendMenu(pop4, MF_STRING, IDM_OPTIONS, TEXT("Options"));
        AppendMenu(pop5, MF_STRING, IDM_ABOUT, TEXT("About"));

        m_rcMenuBar.bottom = GetSystemMetrics(SM_CYMENU);
        SetMenu(hWnd, m_hMenu);
        return 0;
    }
    LRESULT CreateToolBar(HWND hWnd)
    {
        LPITEMIDLIST pidl;
        SHGetSpecialFolderLocation(hWnd, CSIDL_DESKTOP, &pidl);
        SHFILEINFO sfi = {0};
        //从系统里随机抽取icon图标
        HIMAGELIST hImageList = (HIMAGELIST)::SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
        // HIMAGELIST hImageList = ImageList_Create(32, 32, ILC_COLOR32 | ILC_MASK, 0, 0);

        //创建工具条控件
        m_hToolBar = CreateWindow(TOOLBARCLASSNAME, NULL,
                                  WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd, (HMENU)1,
                                  NULL, NULL);

        //设置工具条的图片列表
        ::SendMessage(m_hToolBar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);

        //添加一些按钮到工具条上去
        srand((unsigned int)time(NULL));
        UINT uButtonNums = 5;
        UINT uImgCount = ImageList_GetImageCount(hImageList);
        TBBUTTON tbButtons[uButtonNums] = {
            {MAKELONG(rand() % uImgCount, 0), IDB_BUTTON_START, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("启动")},
            {MAKELONG(rand() % uImgCount, 0), IDB_BUTTON_STOP, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("停止")},
            {MAKELONG(rand() % uImgCount, 0), IDB_BUTTON_TDSET, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("通道设置")},
            {MAKELONG(rand() % uImgCount, 0), IDB_BUTTON_XTSET, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("系统设置")},
            {MAKELONG(rand() % uImgCount, 0), IDB_BUTTON_HELP, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)TEXT("帮助")}};

        ::SendMessage(m_hToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
        ::SendMessage(m_hToolBar, TB_ADDBUTTONS, (WPARAM)uButtonNums, (LPARAM)&tbButtons);

        //自动调整工具条的大小并显示
        ::SendMessage(m_hToolBar, TB_AUTOSIZE, 0, 0);
        ::SendMessage(m_hToolBar, TB_SETSTYLE, 0, TBSTYLE_FLAT | CCS_TOP);
        ::GetWindowRect(m_hToolBar, &m_rcToolBar);
        ::ShowWindow(m_hToolBar, true);
        return 0;
    }
    LRESULT SetCallBack(UINT uCmdID, LRESULT (*lpfnCallback)(HWND, UINT, WPARAM, LPARAM, LPVOID))
    {
        m_lpfnCallback.emplace(uCmdID, lpfnCallback);
        return 0;
    }
    LRESULT OnCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        int loParam = LOWORD(wParam);
        // int hiParam = HIWORD(wParam);
        if (m_lpfnCallback.find(loParam) != m_lpfnCallback.end())
        {
            m_lpfnCallback.at(loParam)(hWnd, uMsg, wParam, lParam, NULL);
        }
        return 0;
    }
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        LPCTSTR lpWindowplace = TEXT("./windowplace.ini");
        if (uMsg == WM_CREATE)
        {
            // Window place
            WINDOWPLACEMENT wp;
            GetPrivateProfileStruct(TEXT("Main"), TEXT("WP"), &wp, sizeof(wp), lpWindowplace);
            SetWindowPlacement(hWnd, &wp);
        }
        else if (uMsg == WM_DESTROY)
        {
            // Window place
            WINDOWPLACEMENT wp;
            GetWindowPlacement(hWnd, &wp);
            WritePrivateProfileStruct(TEXT("Main"), TEXT("WP"), &wp, sizeof(wp), lpWindowplace);
        }
        CMainFrame *pThis = (CMainFrame *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
        if (pThis)
        {
            return pThis->WindowProc(hWnd, uMsg, wParam, lParam);
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_CREATE:
        {
            break;
        }
        case WM_PAINT:
        {
            break;
        }
        case WM_COMMAND:
        {
            OnCommand(hWnd, uMsg, wParam, lParam);
            break;
        }
        case WM_MOUSEMOVE:
        {
            // int xPos = LOWORD(lParam);
            // int yPos = HIWORD(lParam);
            // TCHAR buffer[256];
            // StringCchPrintf(buffer, 256, TEXT("xPos: %d, yPos: %d"), xPos, yPos);
            // SetWindowText(m_hWnd, buffer);
            break;
        }
        case WM_LBUTTONDOWN:
        {
            break;
        }
        case WM_CONTEXTMENU:
        {
            INT xPos = LOWORD(lParam);
            INT yPos = HIWORD(lParam);
            HMENU hPopMenu = CreatePopupMenu();
            AppendMenu(hPopMenu, MF_STRING, 1, TEXT("Cut"));
            AppendMenu(hPopMenu, MF_STRING, 2, TEXT("Copy"));
            AppendMenu(hPopMenu, MF_STRING, 3, TEXT("Paste"));
            TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
                           xPos, yPos, 0, (HWND)wParam, NULL);
            DestroyMenu(hPopMenu);
            break;
        }
        case WM_SIZE:
        {
            EnumChildWindows(hWnd, EnumChildProc, lParam);
            break;
        }
        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
            break;
        }
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
        default:
        {
        }
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    static BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
    {
        SendMessage(hWnd, WM_SIZE, 0, lParam);
        return TRUE;
    }

public:
    HWND m_hWnd;
    HMENU m_hMenu;
    RECT m_rcMenuBar;
    HWND m_hToolBar;
    RECT m_rcToolBar;
    WNDCLASSEX m_wcex;
    HINSTANCE m_hInstance;
    std::map<UINT, LRESULT (*)(HWND, UINT, WPARAM, LPARAM, LPVOID)> m_lpfnCallback;
};

#endif